package study;

import org.apache.log4j.Logger;
import org.jboss.resteasy.core.InjectorFactoryImpl;
import org.jboss.resteasy.core.ValueInjector;
import org.jboss.resteasy.spi.*;
import org.jboss.resteasy.spi.metadata.Parameter;
import org.jboss.resteasy.spi.metadata.ResourceClass;
import org.jboss.resteasy.spi.metadata.ResourceConstructor;
import org.jboss.resteasy.spi.metadata.ResourceLocator;

import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.Type;
import java.util.Map;
/**
 * Created by 徐翔 on 14-3-10.
 */
public class GuiceInjectorFactory implements InjectorFactory {
    private static final Logger log = Logger.getLogger(GuiceInjectorFactory.class);
    private Map<Class<?>, Type> sessionBeanInterface;
    private InjectorFactory delegate = new InjectorFactoryImpl();
    private Jedi jedi;

    public GuiceInjectorFactory(){
        jedi = Jedi.instance;
    }
    @Override
    public ConstructorInjector createConstructor(Constructor constructor, ResteasyProviderFactory resteasyProviderFactory) {
        Class<?> clazz = constructor.getDeclaringClass();
        ConstructorInjector injector = guiceConstructor(clazz);
        if (injector != null) return injector;
        log.debug("No Guice beans found for "+clazz+". Using default ConstructorInjector.");
        return delegate.createConstructor(constructor, resteasyProviderFactory);
    }

    @Override
    public PropertyInjector createPropertyInjector(Class resourceClass, ResteasyProviderFactory resteasyProviderFactory) {
        return new GuicePropertyInject(delegate.createPropertyInjector(resourceClass,resteasyProviderFactory),resourceClass,Jedi.instance);
    }

    @Override
    public ValueInjector createParameterExtractor(Class injectTargetClass, AccessibleObject injectTarget, Class type, Type genericType, Annotation[] annotations, ResteasyProviderFactory factory)
    {
        return delegate.createParameterExtractor(injectTargetClass, injectTarget, type, genericType, annotations, factory);
    }


    @Override
    public ValueInjector createParameterExtractor(Class injectTargetClass, AccessibleObject injectTarget, Class type,
                                                  Type genericType, Annotation[] annotations, boolean useDefault, ResteasyProviderFactory factory)
    {
        return delegate.createParameterExtractor(injectTargetClass, injectTarget, type, genericType, annotations, useDefault, factory);
    }

    @Override
    public ValueInjector createParameterExtractor(Parameter parameter, ResteasyProviderFactory resteasyProviderFactory) {
        return delegate.createParameterExtractor(parameter, resteasyProviderFactory);
    }

    @Override
    public MethodInjector createMethodInjector(ResourceLocator resourceLocator, ResteasyProviderFactory resteasyProviderFactory) {
        return delegate.createMethodInjector(resourceLocator, resteasyProviderFactory);
    }

    @Override
    public PropertyInjector createPropertyInjector(ResourceClass resourceClass, ResteasyProviderFactory resteasyProviderFactory) {
        return new GuicePropertyInject(delegate.createPropertyInjector(resourceClass, resteasyProviderFactory),resourceClass.getClazz(),Jedi.instance);
    }

    @Override
    public ConstructorInjector createConstructor(ResourceConstructor constructor, ResteasyProviderFactory factory) {
        Class<?> clazz = constructor.getConstructor().getDeclaringClass();
        ConstructorInjector injector = guiceConstructor(clazz);
        if (injector != null) return injector;

        log.debug("No Guice beans found for "+clazz+". Using default ConstructorInjector.");
        return delegate.createConstructor(constructor, factory);
    }

    protected ConstructorInjector guiceConstructor(Class<?> clazz){
        if(jedi.getInjector().getAllBindings().containsKey(clazz)){
            return new GuiceConstructorInjector(clazz, Jedi.instance);
        }
        return null;
    }
}
